package com.ict.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ict.common.core.domain.entity.SysDept;
import com.ict.common.utils.SecurityUtils;
import com.ict.common.utils.StringUtils;
import com.ict.common.utils.uuid.IdUtils;
import com.ict.system.mapper.SysDeptMapper;
import com.ict.system.mapper.SysUserRoleMapper;
import com.ict.system.service.ISysDeptService;
import com.ict.web.constant.Constants;
import com.ict.web.constant.ProjectStatusEnum;
import com.ict.web.controller.file.domain.YzqFile;
import com.ict.web.controller.file.dto.YzqFileDTO;
import com.ict.web.controller.file.service.IYzqFileService;
import com.ict.web.domain.*;
import com.ict.web.dto.AnnualDeclarationAddDto;
import com.ict.web.dto.AnnualDeclarationEditDto;
import com.ict.web.dto.ProjectManagementAddDto;
import com.ict.web.mapper.AnnualDeclarationMapper;
import com.ict.web.mapper.AnnualProjectPlanMapper;
import com.ict.web.mapper.ProjectManagementMapper;
import com.ict.web.msg.domain.SysMsg;
import com.ict.web.msg.util.CreateMsgUtil;
import com.ict.web.service.IAnnualDeclarationService;
import com.ict.web.service.IAnnualProjectPlanService;
import com.ict.web.service.IApprovalService;
import com.ict.web.vo.AnnualDeclarationVo;
import com.ict.web.vo.AnnualProjectPlanListVo;
import io.jsonwebtoken.lang.Collections;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.TreeSet;
import java.util.stream.Collectors;

/**
 * 年度申报--刘杰Service业务层处理
 *
 * @author liujie
 * @date 2022-02-25
 */
@Service
public class AnnualDeclarationServiceImpl extends ServiceImpl<AnnualDeclarationMapper,AnnualDeclaration> implements IAnnualDeclarationService
{
    @Resource
    private AnnualDeclarationMapper annualDeclarationMapper;

    @Resource
    private AnnualProjectPlanMapper annualProjectPlanMapper;

    @Resource
    private ProjectManagementServiceImpl projectManagementService;

    @Resource
    private IYzqFileService fileService;
    @Resource
    private ISysDeptService deptService;
    @Resource
    private IApprovalService approvalService;
    @Resource
    private SysUserRoleMapper userRoleMapper;
    @Resource
    private IAnnualProjectPlanService projectPlanService;
    @Resource
    private ProjectManagementMapper projectManagementMapper;
    @Autowired
    private SysDeptMapper sysDeptMapper;

    /**
     * 查询 年度项目计划 名称
     */
    @Override
    public List<AnnualProjectPlanListVo> selectAnnualName(AnnualProjectPlanListVo vo){
        return annualProjectPlanMapper.selectAnnualNameList(vo);
    }

    /**
     * 查询年度申报--刘杰
     *
     * @param annualId 年度申报--刘杰主键
     * @return 年度申报--刘杰
     */
    @Override
    public AnnualDeclarationVo selectAnnualDeclarationByAnnualId(Long annualId)
    {
        AnnualDeclaration annualDeclaration =
                annualDeclarationMapper.selectAnnualDeclarationByAnnualId(annualId);
        Assert.isTrue(StringUtils.isNotNull(annualDeclaration),"未找到年度申报对象");
        AnnualDeclarationVo annualDeclarationVo = new AnnualDeclarationVo();
        BeanUtils.copyProperties(annualDeclaration,annualDeclarationVo);
        YzqFile file = fileService.getById(annualDeclaration.getProjectProposal());
        annualDeclarationVo.setProjectProposalFile(file);
        AnnualProjectPlan annualProjectPlan = annualProjectPlanMapper.selectById(annualDeclaration.getPlanId());
        Assert.isTrue(StringUtils.isNotNull(annualProjectPlan),"未找到该年度申报的年度计划信息");
        annualDeclarationVo.setPlanName(annualProjectPlan.getName());
        annualDeclarationVo.setProjectInvestmentEstimation(annualDeclaration.getProjectInvestmentEstimation().setScale(6, BigDecimal.ROUND_HALF_UP));
        //返回审核进程
        QueryWrapper<ProjectManagement> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id",annualDeclaration.getPlanId());
        queryWrapper.eq("annual_id",annualId);
        ProjectManagement projectManagement = projectManagementService.getOne(queryWrapper);
        Assert.isTrue(StringUtils.isNotNull(projectManagement),"未找到该项目信息");
        List<Approval> courseList = approvalService.lambdaQuery()
                .eq(Approval::getProjectId, projectManagement.getProId())
                .eq(Approval::getDelFlag,ExtractExpert.DELETE_STATUS_NORMAL)
                .eq(Approval::getApprovalStage,ProjectStatusEnum.DECLARATION_SUBMISSION_SUBMITTED.get().getStage())
                .isNotNull(Approval::getApprovalResult)
                .orderByAsc(Approval::getCreateTime).list();
        annualDeclarationVo.setCourseList(courseList);
        return annualDeclarationVo;
    }

    /**
     * 查询年度申报--刘杰列表
     *
     * @param annualDeclaration 年度申报--刘杰
     * @return 年度申报--刘杰
     */
    @Override
    public List<AnnualDeclaration> selectAnnualDeclarationList(AnnualDeclaration annualDeclaration)
    {
        return annualDeclarationMapper.selectAnnualDeclarationList(annualDeclaration);
    }

    /**
     * 新增年度申报--刘杰
     *
     * @param dto 年度申报--刘杰
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insertAnnualDeclaration(AnnualDeclarationAddDto dto)
    {
        //名称重复性校验
        QueryWrapper<AnnualDeclaration> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("entry_name",dto.getEntryName());
        queryWrapper.eq("del_flag", Constants.DELETE_STATUS_NORMAL);
        List<AnnualDeclaration> list = annualDeclarationMapper.selectList(queryWrapper);
        Assert.isTrue(Collections.isEmpty(list),"年度申报项目名称重复");
        AnnualDeclaration bean = AnnualDeclarationAddDto.of(dto);
        AnnualProjectPlan annualProjectPlan = annualProjectPlanMapper.selectById(bean.getPlanId());
        Assert.isTrue(StringUtils.isNotNull(annualProjectPlan),"未找到该年度计划");
        Assert.isTrue(ProjectStatusEnum.ANNUAL_PROJECT_PLAN_REPORTING.get().getStatus().equals(annualProjectPlan.getIsState()),
                "年度计划必须为正在申报状态才能申报");
        String projectPlanName = annualProjectPlan.getName();
        bean.setPlanId(dto.getPlanId());
        bean.setPlanName(annualProjectPlan.getName());
        //同步文件对象
        ArrayList<YzqFile> fileList = AnnualDeclarationAddDto.toFile(bean,dto);
        annualDeclarationMapper.insert(bean);
        fileService.batchInsertFile(fileList);
        // 暂存
        Assert.isTrue(StringUtils.isNotEmpty(dto.getTemporaryFlag()),"暂存标识不能为空");

        //年度申报 添加到 新增项目管理
        ProjectManagementAddDto addDto = new ProjectManagementAddDto();
        //设置项目名称
        addDto.setName(bean.getEntryName());
        //设置项目类别
        addDto.setType(bean.getProjectCategory());
        //设置投资估算
        addDto.setInvestmentEstimation(bean.getProjectInvestmentEstimation().setScale(6, BigDecimal.ROUND_HALF_UP));
        //设置年度申报id
        addDto.setAnnualId(bean.getAnnualId());
        //设置年度计划id
        addDto.setPlanId(dto.getPlanId());
        //设置项目性质:{0:年度项目;1:增补项目;}
        addDto.setNature("0");
        //设置节点 申报提交
        addDto.setNode("0");
        addDto.setStag(ProjectStatusEnum.STATEMENT_NOT_SUBMITTED.get().getStage());
        addDto.setProjectProposal(bean.getProjectProposal());
        if (dto.getTemporaryFlag().equals("1")){
            //设置 状态 （未提交）

            addDto.setIsState(ProjectStatusEnum.STATEMENT_NOT_SUBMITTED.get().getStatus());
            projectManagementService.insertProjectManagement(addDto);
            // 提交-不暂存
        }else if (dto.getTemporaryFlag().equals("0")){
            //设置 状态 （已提交）
            addDto.setIsState(ProjectStatusEnum.DECLARATION_SUBMISSION_SUBMITTED.get().getStatus());
            Long proId = projectManagementService.insertProjectManagement(addDto);
            //项目单位申请年度计划-生成对应系统消息
            String content=CreateMsgUtil.SUBMITTED+projectPlanName+"，请注意查看。";
            String username = SecurityUtils.getUsername();
            //大数据局收到消息
            List<Long> bigDataId = userRoleMapper.getUserIdByRoleId(Constants.ROLE_TYPE_BIGDATA);
            List<Long> bigDataNormalId = userRoleMapper.getUserIdByRoleId(Constants.ROLE_TYPE_BIGDATA_NORMAL);
            bigDataId.addAll(bigDataNormalId);
            bigDataId.forEach(s->{
                CreateMsgUtil.createMsg(content,s,username,CreateMsgUtil.DECLARATION_SUBMISSION_SUBMITTED_TITLE, SysMsg.RESOURCE_TYPE_DATA,String.valueOf(proId), null);
            });
            totalProjectNumber(annualProjectPlan, dto);

        }
        return bean.getAnnualId();
    }

    /**
     * 修改年度申报--刘杰
     *
     * @param annualId 年度申报--刘杰
     * @return 结果
     */
    @Override
    public int updateAnnualDeclaration(AnnualDeclarationEditDto dto,Long annualId)
    {
        AnnualDeclaration bean = annualDeclarationMapper.selectById(annualId);
        Assert.isTrue(StringUtils.isNotNull(bean),"该年度申报不存在");
        if(!dto.getEntryName().equals(bean.getEntryName())){
            QueryWrapper<AnnualDeclaration> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("entry_name",dto.getEntryName());
            queryWrapper.eq("del_flag",Constants.DELETE_STATUS_NORMAL);
            List<AnnualDeclaration> list = annualDeclarationMapper.selectList(queryWrapper);
            Assert.isTrue(Collections.isEmpty(list),"年度申报项目名称重复");
        }
        BeanUtils.copyProperties(dto, bean);
        bean.setUpdateTime(LocalDateTime.now());
        //年度申报修改部分同步数据到项目表中
        ProjectManagement projectManagement = projectManagementService.lambdaQuery().eq(ProjectManagement::getAnnualId, annualId).one();
        Assert.isTrue(StringUtils.isNotNull(projectManagement),"项目信息未关联该年度申报");
        projectManagement.setName(bean.getEntryName());
        projectManagement.setType(bean.getProjectCategory());
        projectManagement.setInvestmentEstimation(bean.getProjectInvestmentEstimation().setScale(6,BigDecimal.ROUND_HALF_UP));
        if (ProjectStatusEnum.APPLICATION_REVIEW_RETURN_MODIFICATION.get().getStatus().equals(projectManagement.getIsState())
                ||ProjectStatusEnum.APPLICATION_UPDATE_RETURN_MODIFICATION.get().getStatus().equals(projectManagement.getIsState())
                ||ProjectStatusEnum.APPLICATION_UPDATE_TO_BE_SUBMITTED.get().getStatus().equals(projectManagement.getIsState())) {
            projectManagement.setIsState(ProjectStatusEnum.APPLICATION_UPDATE_TO_BE_SUBMITTED.get().getStatus());
            projectManagement.setNode(ProjectStatusEnum.APPLICATION_UPDATE_TO_BE_SUBMITTED.get().getNode());
            //修改提交项目申报时更新申报修改状态为待审核
            if(dto.getTemporaryFlag().equals("0")){
                //退回修改更新结束时间
                Approval approval = approvalService.getApproval(projectManagement.getProId(), ProjectStatusEnum.APPLICATION_UPDATE_RETURN_MODIFICATION.get().getStatus(), null, null);
                if(StringUtils.isNotNull(approval)){
                    approval.setEndTime(LocalDateTime.now());
                    approvalService.updateById(approval);
                }
                Approval approval1 = approvalService.getApproval(projectManagement.getProId(), ProjectStatusEnum.APPLICATION_REVIEW_RETURN_MODIFICATION.get().getStatus(), null, null);
                if(StringUtils.isNotNull(approval1)){
                    approval1.setEndTime(LocalDateTime.now());
                    approvalService.updateById(approval1);
                }

                projectManagement.setIsState(ProjectStatusEnum.APPLICATION_UPDATE_TO_BE_APPROVED.get().getStatus());
                approvalService.save(new Approval(IdUtils.snowId(),projectManagement.getProId(),ProjectStatusEnum.APPLICATION_UPDATE_TO_BE_APPROVED.get().getStage(),
                        ProjectStatusEnum.APPLICATION_UPDATE_TO_BE_APPROVED.get().getNode(),LocalDateTime.now(),null,null,ProjectStatusEnum.APPLICATION_UPDATE_TO_BE_APPROVED.get().getStatus(),
                        "/",null, null,null, LocalDateTime.now(),Approval.APPROVAL_TYPE_PROJECT_MANAGE));
                //申报审核更新结束时间
                List<Approval> approvalList = approvalService.lambdaQuery().eq(Approval::getApprovalStatus, ProjectStatusEnum.APPLICATION_REVIEW_RETURN_MODIFICATION.get().getStatus())
                        .eq(Approval::getProjectId,projectManagement.getProId()).list();
                approvalList.stream().forEach(s->s.setEndTime(LocalDateTime.now()));
                approvalService.saveOrUpdateBatch(approvalList);
            }
        }else if (ProjectStatusEnum.STATEMENT_NOT_SUBMITTED.get().getStatus().equals(projectManagement.getIsState())){
            // 修改年度申报提交审核
            if (dto.getTemporaryFlag().equals("1")){
                //设置 状态 （未提交）
                projectManagement.setIsState(ProjectStatusEnum.STATEMENT_NOT_SUBMITTED.get().getStatus());
                projectManagement.setNode(ProjectStatusEnum.STATEMENT_NOT_SUBMITTED.get().getNode());
                // 提交-不暂存
            }else if (dto.getTemporaryFlag().equals("0")){
                //年度申报
                approvalService.save(new Approval(IdUtils.snowId(),projectManagement.getProId(),ProjectStatusEnum.DECLARATION_SUBMISSION_SUBMITTED.get().getStage(),
                        ProjectStatusEnum.DECLARATION_SUBMISSION_SUBMITTED.get().getNode(),LocalDateTime.now(),LocalDateTime.now(),SecurityUtils.getNickName(),ProjectStatusEnum.DECLARATION_SUBMISSION_SUBMITTED.get().getStatus(),
                        "/",null, null,null, LocalDateTime.now(),Approval.APPROVAL_TYPE_PROJECT_MANAGE));

                //设置 状态 （已提交）
                projectManagement.setIsState(ProjectStatusEnum.DECLARATION_SUBMISSION_SUBMITTED.get().getStatus());
                projectManagement.setNode(ProjectStatusEnum.DECLARATION_SUBMISSION_SUBMITTED.get().getNode());
                //项目单位申请年度计划-生成对应系统消息
                String content=CreateMsgUtil.SUBMITTED+dto.getPlanName()+"，请注意查看。";
                String username = SecurityUtils.getUsername();
                //大数据局收到消息
                List<Long> bigDataId = userRoleMapper.getUserIdByRoleId(Constants.ROLE_TYPE_BIGDATA);
                List<Long> bigDataNormalId = userRoleMapper.getUserIdByRoleId(Constants.ROLE_TYPE_BIGDATA_NORMAL);
                bigDataId.addAll(bigDataNormalId);
                bigDataId.forEach(s->{
                    CreateMsgUtil.createMsg(content,s,username,CreateMsgUtil.DECLARATION_SUBMISSION_SUBMITTED_TITLE, SysMsg.RESOURCE_TYPE_DATA,String.valueOf(projectManagement.getProId()), null);
                });

                AnnualProjectPlan annualProjectPlan = annualProjectPlanMapper.selectById(projectManagement.getPlanId());
                AnnualDeclarationAddDto annualDeclarationAddDto = new AnnualDeclarationAddDto();
                BeanUtils.copyProperties(dto,annualDeclarationAddDto);
                totalProjectNumber(annualProjectPlan,annualDeclarationAddDto);
            }
        }

        //更新文件信息
        YzqFile filePro = fileService.getById(bean.getProjectProposal());
        YzqFileDTO fileDTO = dto.getProjectProposal();
        BeanUtils.copyProperties(fileDTO,filePro);
        fileService.updateById(filePro);
        projectManagementService.updateById(projectManagement);
        return annualDeclarationMapper.updateById(bean);
    }

    /**
     * 删除年度申报--刘杰信息
     *
     * @param annualId 年度申报--刘杰主键
     * @return 结果
     */
    @Override
    public int deleteAnnualDeclarationByAnnualId(Long annualId)
    {
        AnnualDeclaration bean = annualDeclarationMapper.selectById(annualId);
        bean.setDelFlag("1");
        return annualDeclarationMapper.updateById(bean);
    }

    /**
     * 统计项目单位数量、项目数量、总金额、各类项目数量
     */
    @Override
    public void totalProjectNumber(AnnualProjectPlan annualProjectPlan, AnnualDeclarationAddDto dto){
        SysDept sysDept = deptService.selectDeptById(SecurityUtils.getDeptId());

        LambdaQueryWrapper<ProjectManagement> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ProjectManagement::getPlanId,annualProjectPlan.getPlanId())
                .eq(ProjectManagement::getIsDelete,Constants.DELETE_STATUS_NORMAL)
                .ne(ProjectManagement::getIsState,ProjectStatusEnum.STATEMENT_NOT_SUBMITTED.get().getStatus());
        List<ProjectManagement> projectManagements = projectManagementMapper.selectList(lambdaQueryWrapper);
        /*List<ProjectManagement> collect = projectManagements.stream().filter(s -> s.getCompany().equals(sysDept.getDeptName())).collect(Collectors.toList());
        if (collect.isEmpty()) {
            annualProjectPlan.setNumberProjectUnits(annualProjectPlan.getNumberProjectUnits()+1);
        }*/
        //设置 项目单位数量
        ArrayList<ProjectManagement> collect1 =
                projectManagements.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
                        -> new TreeSet<>(Comparator.comparing(ProjectManagement::getCompany))), ArrayList::new));
        annualProjectPlan.setNumberProjectUnits(Long.valueOf(collect1.size()));


        annualProjectPlan.setNumberItems(annualProjectPlan.getNumberItems()+1);

        BigDecimal decimal = annualProjectPlan.getTotalInvestmentEstimation().add(dto.getProjectInvestmentEstimation());
        annualProjectPlan.setTotalInvestmentEstimation(decimal);

        switch (dto.getProjectCategory()){
            case "0":
                annualProjectPlan.setConstructionProjects(annualProjectPlan.getConstructionProjects()+1);
                break;
            case "1":
                annualProjectPlan.setConstructionProjects(annualProjectPlan.getConstructionProjects()+1);
                break;
            case "2":
                annualProjectPlan.setPurchaseItems(annualProjectPlan.getPurchaseItems()+1);
                break;
            case "3":
                annualProjectPlan.setOperationMaintenance(annualProjectPlan.getOperationMaintenance()+1);
                break;
            case "4":
                annualProjectPlan.setOther(annualProjectPlan.getOther()+1);
                break;

        }
        annualProjectPlanMapper.updateById(annualProjectPlan);
    }

    @Override
    public String[] getUnitAndDept(String orgCategory) {
        List<SysDept> list = sysDeptMapper.getUnitAndDept(orgCategory);
        List<String> collect = list.stream().map(SysDept::getDeptName).collect(Collectors.toList());
        String[] strings = new String[collect.size()];
        return collect.toArray(strings);
    }
}
